﻿using Hangfire;
using Hangfire.Console;
using Hangfire.Server;
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Threading.Tasks;

namespace HangfireLearn.Task
{
    /// <summary>
    /// Job的具体执行类，由HangfireTask来使用
    /// 不需要注册到DI中，Hangfire会自动注入
    /// </summary>
    public class Jobs
    {
        IConfiguration configuration;

        public Jobs(IConfiguration configuration)
        {
            this.configuration = configuration;
        }

        /// <summary>
        /// 执行简单任务，任务上下文PerformContext context会自动设置
        /// </summary>
        /// <param name="context"></param>
        [AutomaticRetry(Attempts = 3)]  //任务失败自动重试3次
        [DisplayName("简单任务, Id:{0}")] //设置显示的控制台的名称
        public void DoSimpleJob(int id,PerformContext context, IJobCancellationToken cancellationToken)
        {
            //抛出异常，触发Job失败
            //throw new Exception("测试的异常");
            JobWithConsole(context, cancellationToken, "HangfireTask:Fire-and-forget tasks run ...!");
            
        }

        /// <summary>
        /// 延时任务
        /// </summary>
        /// <param name="id"></param>
        /// <param name="context">Hangfire上下文，Hangfire调试时会自动传入</param>
        /// <param name="cancellationToken">Hangfire调试时的取消token</param>
        [AutomaticRetry(Attempts = 3)]  //任务失败自动重试3次
        [DisplayName("延时任务, Id:{0}")] //设置显示的控制台的名称
        public void DoDelayJob(int id,PerformContext context,IJobCancellationToken cancellationToken)
        {
            JobWithConsole(context, cancellationToken, "HangfireTask: Delayed tasks run...!");
        }

        /// <summary>
        /// 周期循环任务
        /// </summary>
        /// <param name="context">Hangfire上下文，Hangfire调试时会自动传入</param>
        /// <param name="cancellationToken">Hangfire调试时的取消token</param>
        [DisplayName("循环任务")] //设置显示的控制台的名称
        [DisableConcurrentExecution(5 * 60)] //Job不能并行执行
        public void DoRecurringJob(PerformContext context, IJobCancellationToken cancellationToken)
        {
            JobWithConsole(context, cancellationToken,"HangfireTask:Recurring tasks run ...! ");
        }

        /// <summary>
        /// 执行任务，输出到Hangfire Console
        /// </summary>
        /// <param name="context"></param>
        private void JobWithConsole(PerformContext context, IJobCancellationToken cancellationToken, string msg)
        {
            string jobId = context.BackgroundJob.Id;
            int retryCount = context.GetJobParameter<int>("RetryCount");

            //输出日志
            context.WriteLine($"{DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")} - {msg}");

            var progressBar = context.WriteProgressBar();

            //进度条
            // create progress bar
            //var progress = context.WriteProgressBar();
            // update value for previously created progress bar
            //progress.SetValue(100);

            //或

            //取消令牌通过 IJobCancellationToken 的接口暴露出来。
            foreach (var i in Enumerable.Range(1, 50).ToList().WithProgress(progressBar))
            {
                //当关机请求时，结束任务
                //if (cancellationToken.ShutdownToken.IsCancellationRequested) return;

                //当发起取消任务请求时，可通过 ThrowIfCancellationRequested 方法来抛出 OperationCanceledException :
                //这样任务可以进入重试
                cancellationToken.ThrowIfCancellationRequested();

                System.Threading.Thread.Sleep(500);
            }
        }
    }
}
